home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / message.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-08-28  |  56.9 KB  |  2,575 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * message.c: functions for displaying messages on the command line
  12.  */
  13.  
  14. #define MESSAGE_FILE        /* don't include prototype for smsg() */
  15.  
  16. #include "vim.h"
  17.  
  18. #ifdef __QNX__
  19. # include <stdarg.h>
  20. #endif
  21.  
  22. static void reset_last_sourcing __ARGS((void));
  23. static void add_msg_hist __ARGS((char_u *s, int len, int attr));
  24. static void hit_return_msg __ARGS((void));
  25. static void msg_home_replace_attr __ARGS((char_u *fname, int attr));
  26. #ifdef FEAT_MBYTE
  27. static char_u *screen_puts_mbyte __ARGS((char_u *s, int l, int attr));
  28. #endif
  29. static int  msg_use_printf __ARGS((void));
  30. static void msg_screen_putchar __ARGS((int c, int attr));
  31. static int  msg_check_screen __ARGS((void));
  32. static void redir_write __ARGS((char_u *s));
  33. #ifdef FEAT_CON_DIALOG
  34. static char_u *msg_show_console_dialog __ARGS((char_u *message, char_u *buttons, int dfltbutton));
  35. static int msg_noquit_more = FALSE; /* quit not allowed at more prompt */
  36. #endif
  37.  
  38. struct msg_hist
  39. {
  40.     struct msg_hist    *next;
  41.     char_u        *msg;
  42.     int            attr;
  43. };
  44.  
  45. static struct msg_hist *first_msg_hist = NULL;
  46. static struct msg_hist *last_msg_hist = NULL;
  47. static int msg_hist_len = 0;
  48. static int msg_hist_off = FALSE;    /* don't add messages to history */
  49.  
  50. /*
  51.  * When writing messages to the screen, there are many different situations.
  52.  * A number of variables is used to remember the current state:
  53.  * msg_didany        TRUE when messages were written since the last time the
  54.  *            user reacted to a prompt.
  55.  *            Reset: After hitting a key for the hit-return prompt,
  56.  *            hitting <CR> for the command line or input().
  57.  *            Set: When any message is written to the screen.
  58.  * msg_didout        TRUE when something was written to the current line.
  59.  *            Reset: When advancing to the next line, when the current
  60.  *            text can be overwritten.
  61.  *            Set: When any message is written to the screen.
  62.  * msg_nowait        No extra delay for the last drawn message.
  63.  *            Used in normal_cmd() before the mode message is drawn.
  64.  * emsg_on_display  There was an error message recently.  Indicates that there
  65.  *            should be a delay before redrawing.
  66.  * msg_scroll        The next message should not overwrite the current one.
  67.  * msg_scrolled        How many lines the screen has been scrolled (because of
  68.  *            messages).  Used in update_screen() to scroll the screen
  69.  *            back.  Incremented each time the screen scrolls a line.
  70.  * msg_scrolled_ign  TRUE when msg_scrolled is non-zero and msg_puts_attr()
  71.  *            writes something without scrolling should not make
  72.  *            need_wait_return to be set.  This is a hack to make ":ts"
  73.  *            work without an extra prompt.
  74.  * lines_left        Number of lines available for messages before the
  75.  *            more-prompt is to be given.
  76.  * need_wait_return TRUE when the hit-return prompt is needed.
  77.  *            Reset: After giving the hit-return prompt, when the user
  78.  *            has answered some other prompt.
  79.  *            Set: When the ruler or typeahead display is overwritten,
  80.  *            scrolling the screen for some message.
  81.  * keep_msg        Message to be displayed after redrawing the screen, in
  82.  *            main_loop().
  83.  *            This is an allocated string or NULL when not used.
  84.  */
  85.  
  86. /*
  87.  * msg(s) - displays the string 's' on the status line
  88.  * When terminal not initialized (yet) mch_errmsg(..) is used.
  89.  * return TRUE if wait_return not called
  90.  */
  91.     int
  92. msg(s)
  93.     char_u    *s;
  94. {
  95.     return msg_attr_keep(s, 0, FALSE);
  96. }
  97.  
  98.     int
  99. msg_attr(s, attr)
  100.     char_u    *s;
  101.     int        attr;
  102. {
  103.     return msg_attr_keep(s, attr, FALSE);
  104. }
  105.  
  106.     int
  107. msg_attr_keep(s, attr, keep)
  108.     char_u    *s;
  109.     int        attr;
  110.     int        keep;        /* TRUE: set keep_msg if it doesn't scroll */
  111. {
  112.     static int    entered = 0;
  113.     int        retval;
  114.     char_u    *buf = NULL;
  115.  
  116. #ifdef FEAT_EVAL
  117.     if (attr == 0)
  118.     set_vim_var_string(VV_STATUSMSG, s, -1);
  119. #endif
  120.  
  121.     /*
  122.      * It is possible that displaying a messages causes a problem (e.g.,
  123.      * when redrawing the window), which causes another message, etc..    To
  124.      * break this loop, limit the recursiveness to 3 levels.
  125.      */
  126.     if (entered >= 3)
  127.     return TRUE;
  128.     ++entered;
  129.  
  130.     /* Add message to history (unless it's a repeated kept message or a
  131.      * truncated message) */
  132.     if (s != keep_msg
  133.         || (*s != '<'
  134.         && last_msg_hist != NULL
  135.         && last_msg_hist->msg != NULL
  136.         && STRCMP(s, last_msg_hist->msg)))
  137.     add_msg_hist(s, -1, attr);
  138.  
  139.     /* When displaying keep_msg, don't let msg_start() free it, caller must do
  140.      * that. */
  141.     if (s == keep_msg)
  142.     keep_msg = NULL;
  143.  
  144.     /* Truncate the message if needed. */
  145.     buf = msg_strtrunc(s);
  146.     if (buf != NULL)
  147.     s = buf;
  148.  
  149.     msg_start();
  150.     msg_outtrans_attr(s, attr);
  151.     if (msg_silent == 0)
  152.     msg_clr_eos();
  153.     retval = msg_end();
  154.  
  155.     if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1)
  156.                                * Columns + sc_col)
  157.     {
  158.     set_keep_msg(s);
  159.     keep_msg_attr = 0;
  160.     }
  161.  
  162.     vim_free(buf);
  163.     --entered;
  164.     return retval;
  165. }
  166.  
  167. /*
  168.  * Truncate a string such that it can be printed without causing a scroll.
  169.  * Returns an allocated string or NULL when no truncating is done.
  170.  */
  171.     char_u *
  172. msg_strtrunc(s)
  173.     char_u    *s;
  174. {
  175.     char_u    *buf = NULL;
  176.     int        len;
  177.     int        room;
  178.  
  179.     /* May truncate message to avoid a hit-return prompt */
  180.     if (!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL)
  181.                                 && !exmode_active)
  182.     {
  183.     len = vim_strsize(s);
  184.     room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
  185.     if (len > room && room > 0)
  186.     {
  187. #ifdef FEAT_MBYTE
  188.         if (enc_utf8)
  189.         /* may have up to 18 bytes per cell (6 per char, up to two
  190.          * composing chars) */
  191.         buf = alloc((room + 2) * 18);
  192.         else if (enc_dbcs == DBCS_JPNU)
  193.         /* may have up to 2 bytes per cell for euc-jp */
  194.         buf = alloc((room + 2) * 2);
  195.         else
  196. #endif
  197.         buf = alloc(room + 2);
  198.         if (buf != NULL)
  199.         trunc_string(s, buf, room);
  200.     }
  201.     }
  202.     return buf;
  203. }
  204.  
  205. /*
  206.  * Truncate a string "s"  to "buf" with cell width "room".
  207.  * "s" and "buf" may be equal.
  208.  */
  209.     void
  210. trunc_string(s, buf, room)
  211.     char_u    *s;
  212.     char_u    *buf;
  213.     int        room;
  214. {
  215.     int        half;
  216.     int        len;
  217.     int        e;
  218.     int        i;
  219.     int        n;
  220.  
  221.     room -= 3;
  222.     half = room / 2;
  223.     len = 0;
  224.  
  225.     /* First part: Start of the string. */
  226.     for (e = 0; len < half; ++e)
  227.     {
  228.     n = ptr2cells(s + e);
  229.     if (len + n >= half)
  230.         break;
  231.     len += n;
  232.     buf[e] = s[e];
  233. #ifdef FEAT_MBYTE
  234.     if (has_mbyte)
  235.         for (n = (*mb_ptr2len_check)(s + e); --n > 0; )
  236.         {
  237.         ++e;
  238.         buf[e] = s[e];
  239.         }
  240. #endif
  241.     }
  242.  
  243.     /* Last part: End of the string. */
  244.     i = e;
  245. #ifdef FEAT_MBYTE
  246.     if (enc_dbcs != 0)
  247.     {
  248.     /* For DBCS going backwards in a string is slow, but
  249.      * computing the cell width isn't too slow: go forward
  250.      * until the rest fits. */
  251.     n = vim_strsize(s + i);
  252.     while (len + n > room)
  253.     {
  254.         n -= ptr2cells(s + i);
  255.         i += (*mb_ptr2len_check)(s + i);
  256.     }
  257.     }
  258.     else if (enc_utf8)
  259.     {
  260.     /* For UTF-8 we can go backwards easily. */
  261.     i = (int)STRLEN(s);
  262.     for (;;)
  263.     {
  264.         half = i - (*mb_head_off)(s, s + i - 1) - 1;
  265.         n = ptr2cells(s + half);
  266.         if (len + n > room)
  267.         break;
  268.         len += n;
  269.         i = half;
  270.     }
  271.     }
  272.     else
  273. #endif
  274.     {
  275.     for (i = (int)STRLEN(s); len + (n = ptr2cells(s + i - 1)) <= room; --i)
  276.         len += n;
  277.     }
  278.  
  279.     /* Set the middle and copy the last part. */
  280.     mch_memmove(buf + e, "...", (size_t)3);
  281.     mch_memmove(buf + e + 3, s + i, STRLEN(s + i) + 1);
  282. }
  283.  
  284. /*
  285.  * Automatic prototype generation does not understand this function.
  286.  * Note: Caller of smgs() and smsg_attr() must check the resulting string is
  287.  * shorter than IOSIZE!!!
  288.  */
  289. #ifndef PROTO
  290. # ifndef __QNX__
  291.  
  292. int
  293. #ifdef __BORLANDC__
  294. _RTLENTRYF
  295. #endif
  296. smsg __ARGS((char_u *, long, long, long,
  297.             long, long, long, long, long, long, long));
  298. int
  299. #ifdef __BORLANDC__
  300. _RTLENTRYF
  301. #endif
  302. smsg_attr __ARGS((int, char_u *, long, long, long,
  303.             long, long, long, long, long, long, long));
  304.  
  305. /* VARARGS */
  306.     int
  307. #ifdef __BORLANDC__
  308. _RTLENTRYF
  309. #endif
  310. smsg(s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  311.     char_u    *s;
  312.     long    a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
  313. {
  314.     return smsg_attr(0, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  315. }
  316.  
  317. /* VARARGS */
  318.     int
  319. #ifdef __BORLANDC__
  320. _RTLENTRYF
  321. #endif
  322. smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  323.     int        attr;
  324.     char_u    *s;
  325.     long    a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
  326. {
  327.     sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  328.     return msg_attr(IObuff, attr);
  329. }
  330.  
  331. # else /* __QNX__ */
  332.  
  333.     int
  334. smsg(char_u *s, ...)
  335. {
  336.     va_list arglist;
  337.  
  338.     va_start(arglist, s);
  339.     vsprintf((char *)IObuff, (char *)s, arglist);
  340.     va_end(arglist);
  341.     return msg(IObuff);
  342. }
  343.  
  344.     int
  345. smsg_attr(int attr, char_u *s, ...)
  346. {
  347.     va_list arglist;
  348.  
  349.     va_start(arglist, s);
  350.     vsprintf((char *)IObuff, (char *)s, arglist);
  351.     va_end(arglist);
  352.     return msg_attr(IObuff, attr);
  353. }
  354.  
  355. # endif /* __QNX__ */
  356. #endif
  357.  
  358. /*
  359.  * Remember the last sourcing name/lnum used in an error message, so that it
  360.  * isn't printed each time when it didn't change.
  361.  */
  362. static int    last_sourcing_lnum = 0;
  363. static char_u   *last_sourcing_name = NULL;
  364.  
  365. /*
  366.  * Reset the last used sourcing name/lnum.  Makes sure it is displayed again
  367.  * for the next error message;
  368.  */
  369.     static void
  370. reset_last_sourcing()
  371. {
  372.     vim_free(last_sourcing_name);
  373.     last_sourcing_name = NULL;
  374.     last_sourcing_lnum = 0;
  375. }
  376.  
  377. /*
  378.  * emsg() - display an error message
  379.  *
  380.  * Rings the bell, if appropriate, and calls message() to do the real work
  381.  * When terminal not initialized (yet) mch_errmsg(..) is used.
  382.  *
  383.  * return TRUE if wait_return not called
  384.  */
  385.     int
  386. emsg(s)
  387.     char_u    *s;
  388. {
  389.     char_u    *Buf;
  390.     int        attr;
  391.     int        other_sourcing_name;
  392.     char    *p;
  393.  
  394.     /*
  395.      * If "emsg_off" is set: no error messages at the moment.
  396.      * If 'debug' is set: do error message anyway, but without side effects.
  397.      * If "emsg_skip" is set: never do error messages.
  398.      */
  399.     if ((emsg_off > 0 && *p_debug == NUL)
  400. #ifdef FEAT_EVAL
  401.         || emsg_skip > 0
  402. #endif
  403.         )
  404.     return TRUE;
  405.  
  406.     if (!emsg_off)
  407.     {
  408. #ifdef FEAT_EVAL
  409.     /* set "v:errmsg", also when using ":silent! cmd" */
  410.     set_vim_var_string(VV_ERRMSG, s, -1);
  411. #endif
  412.  
  413.     /*
  414.      * When using ":silent! cmd" ignore error messsages.
  415.      * But do write it to the redirection file.
  416.      */
  417.     if (emsg_silent != 0)
  418.     {
  419.         redir_write(s);
  420.         return TRUE;
  421.     }
  422.  
  423.     /* Reset msg_silent, an error causes messages to be switched back on. */
  424.     msg_silent = 0;
  425.     cmd_silent = FALSE;
  426.  
  427.     if (global_busy)        /* break :global command */
  428.         ++global_busy;
  429.  
  430.     if (p_eb)
  431.         beep_flush();        /* also includes flush_buffers() */
  432.     else
  433.         flush_buffers(FALSE);    /* flush internal buffers */
  434.     did_emsg = TRUE;        /* flag for DoOneCmd() */
  435.  
  436. #ifdef VIMBUDDY
  437.     if (sourcing_name == NULL)
  438.     {
  439.         VimBuddyText(s, 2);
  440.         return TRUE;
  441.     }
  442. #endif
  443.     }
  444.  
  445.     emsg_on_display = TRUE;    /* remember there is an error message */
  446.     ++msg_scroll;        /* don't overwrite a previous message */
  447.     attr = hl_attr(HLF_E);    /* set highlight mode for error messages */
  448.     if (msg_scrolled)
  449.     need_wait_return = TRUE;    /* needed in case emsg() is called after
  450.                      * wait_return has reset need_wait_return
  451.                      * and a redraw is expected because
  452.                      * msg_scrolled is non-zero */
  453.  
  454. /*
  455.  * First output name and line number of source of error message
  456.  */
  457.     if (sourcing_name != NULL)
  458.     {
  459.     if (last_sourcing_name != NULL)
  460.         other_sourcing_name = STRCMP(sourcing_name, last_sourcing_name);
  461.     else
  462.         other_sourcing_name = TRUE;
  463.     }
  464.     else
  465.     other_sourcing_name = FALSE;
  466.  
  467.     p = _("Error detected while processing %s:");
  468.     if (sourcing_name != NULL
  469.         && (other_sourcing_name || sourcing_lnum != last_sourcing_lnum)
  470.         && (Buf = alloc((unsigned)(STRLEN(sourcing_name)
  471.                                + STRLEN(p)))) != NULL)
  472.     {
  473.     ++no_wait_return;
  474.     if (other_sourcing_name)
  475.     {
  476.         sprintf((char *)Buf, p, sourcing_name);
  477.         msg_attr(Buf, attr);
  478.     }
  479.         /* lnum is 0 when executing a command from the command line
  480.          * argument, we don't want a line number then */
  481.     if (sourcing_lnum != 0)
  482.     {
  483.         sprintf((char *)Buf, _("line %4ld:"), (long)sourcing_lnum);
  484.         msg_attr(Buf, hl_attr(HLF_N));
  485.     }
  486.     --no_wait_return;
  487.     last_sourcing_lnum = sourcing_lnum;  /* only once for each line */
  488.     vim_free(Buf);
  489.     }
  490.  
  491.     /* remember the last sourcing name printed, also when it's empty */
  492.     if (sourcing_name == NULL || other_sourcing_name)
  493.     {
  494.     vim_free(last_sourcing_name);
  495.     if (sourcing_name == NULL)
  496.         last_sourcing_name = NULL;
  497.     else
  498.         last_sourcing_name = vim_strsave(sourcing_name);
  499.     }
  500.     msg_nowait = FALSE;            /* wait for this msg */
  501.  
  502.     return msg_attr(s, attr);
  503. }
  504.  
  505.     int
  506. emsg2(s, a1)
  507.     char_u *s, *a1;
  508. {
  509.     if ((emsg_off > 0 && *p_debug == NUL)
  510. #ifdef FEAT_EVAL
  511.         || emsg_skip > 0
  512. #endif
  513.         )
  514.     return TRUE;        /* no error messages at the moment */
  515.  
  516.     /* Check for NULL strings (just in case) */
  517.     if (a1 == NULL)
  518.     a1 = (char_u *)"[NULL]";
  519.     /* Check for very long strings (can happen with ":help ^A<CR>").
  520.      * Careful, the argument could actually be a long. */
  521.     if (STRLEN(s) + (strstr((char *)s, "%s") != NULL ? STRLEN(a1) : 20)
  522.                                 >= (size_t)IOSIZE)
  523.     a1 = (char_u *)_("[string too long]");
  524.     sprintf((char *)IObuff, (char *)s, (char *)a1);
  525.     return emsg(IObuff);
  526. }
  527.  
  528.     int
  529. emsgn(s, n)
  530.     char_u    *s;
  531.     long    n;
  532. {
  533.     if ((emsg_off > 0 && *p_debug == NUL)
  534. #ifdef FEAT_EVAL
  535.         || emsg_skip > 0
  536. #endif
  537.         )
  538.     return TRUE;        /* no error messages at the moment */
  539.     sprintf((char *)IObuff, (char *)s, n);
  540.     return emsg(IObuff);
  541. }
  542.  
  543. /*
  544.  * Like msg(), but truncate to a single line if p_shm contains 't', or when
  545.  * "force" is TRUE.  This truncates in another way as for normal messages.
  546.  * Careful: The string may be changed by msg_may_trunc()!
  547.  * Returns a pointer to the printed message, if wait_return() not called.
  548.  */
  549.     char_u *
  550. msg_trunc_attr(s, force, attr)
  551.     char_u    *s;
  552.     int        force;
  553.     int        attr;
  554. {
  555.     int        n;
  556.  
  557.     /* Add message to history before truncating */
  558.     add_msg_hist(s, -1, attr);
  559.  
  560.     s = msg_may_trunc(force, s);
  561.  
  562.     msg_hist_off = TRUE;
  563.     n = msg_attr(s, attr);
  564.     msg_hist_off = FALSE;
  565.  
  566.     if (n)
  567.     return s;
  568.     return NULL;
  569. }
  570.  
  571. /*
  572.  * Check if message "s" should be truncated at the start (for filenames).
  573.  * Return a pointer to where the truncated message starts.
  574.  * Note: May change the message by replacing a character with '<'.
  575.  */
  576.     char_u *
  577. msg_may_trunc(force, s)
  578.     int        force;
  579.     char_u    *s;
  580. {
  581.     int        n;
  582.     int        room;
  583.  
  584.     room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1;
  585.     if ((force || (shortmess(SHM_TRUNC) && !exmode_active))
  586.         && (n = (int)STRLEN(s) - room) > 0)
  587.     {
  588. #ifdef FEAT_MBYTE
  589.     if (has_mbyte)
  590.     {
  591.         int    size = vim_strsize(s);
  592.  
  593.         for (n = 0; size >= room; )
  594.         {
  595.         size -= (*mb_ptr2cells)(s + n);
  596.         n += (*mb_ptr2len_check)(s + n);
  597.         }
  598.         --n;
  599.     }
  600. #endif
  601.     s += n;
  602.     *s = '<';
  603.     }
  604.     return s;
  605. }
  606.  
  607.     static void
  608. add_msg_hist(s, len, attr)
  609.     char_u    *s;
  610.     int        len;        /* -1 for undetermined length */
  611.     int        attr;
  612. {
  613.     struct msg_hist *p;
  614.  
  615.     if (msg_hist_off)
  616.     return;
  617.  
  618.     /* Don't let the message history get too big */
  619.     while (msg_hist_len > 20)
  620.     {
  621.     p = first_msg_hist;
  622.     first_msg_hist = p->next;
  623.     vim_free(p->msg);
  624.     vim_free(p);
  625.     --msg_hist_len;
  626.     }
  627.     /* allocate an entry and add the message at the end of the history */
  628.     p = (struct msg_hist *)alloc((int)sizeof(struct msg_hist));
  629.     if (p != NULL)
  630.     {
  631.     if (len < 0)
  632.         len = (int)STRLEN(s);
  633.     /* remove leading and trailing newlines */
  634.     while (len > 0 && *s == '\n')
  635.     {
  636.         ++s;
  637.         --len;
  638.     }
  639.     while (len > 0 && s[len - 1] == '\n')
  640.         --len;
  641.     p->msg = vim_strnsave(s, len);
  642.     p->next = NULL;
  643.     p->attr = attr;
  644.     if (last_msg_hist != NULL)
  645.         last_msg_hist->next = p;
  646.     last_msg_hist = p;
  647.     if (first_msg_hist == NULL)
  648.         first_msg_hist = last_msg_hist;
  649.     ++msg_hist_len;
  650.     }
  651. }
  652.  
  653. /*
  654.  * ":messages" command.
  655.  */
  656. /*ARGSUSED*/
  657.     void
  658. ex_messages(eap)
  659.     exarg_T    *eap;
  660. {
  661.     struct msg_hist *p;
  662.     char_u        *s;
  663.  
  664.     msg_hist_off = TRUE;
  665.  
  666.     s = mch_getenv((char_u *)"LANG");
  667.     if (s != NULL && *s != NUL)
  668.     msg_attr((char_u *)
  669.         _("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
  670.         hl_attr(HLF_T));
  671.  
  672.     for (p = first_msg_hist; p != NULL; p = p->next)
  673.     if (p->msg != NULL)
  674.         msg_attr(p->msg, p->attr);
  675.  
  676.     msg_hist_off = FALSE;
  677. }
  678.  
  679. #if defined(FEAT_CON_DIALOG) || defined(PROTO)
  680. static void msg_end_prompt __ARGS((void));
  681.  
  682. /*
  683.  * Call this after prompting the user.  This will avoid a hit-return message
  684.  * and a delay.
  685.  */
  686.     static void
  687. msg_end_prompt()
  688. {
  689.     need_wait_return = FALSE;
  690.     emsg_on_display = FALSE;
  691.     cmdline_row = msg_row;
  692.     msg_col = 0;
  693.     msg_clr_eos();
  694. }
  695. #endif
  696.  
  697. /*
  698.  * wait for the user to hit a key (normally a return)
  699.  * if 'redraw' is TRUE, clear and redraw the screen
  700.  * if 'redraw' is FALSE, just redraw the screen
  701.  * if 'redraw' is -1, don't redraw at all
  702.  */
  703.     void
  704. wait_return(redraw)
  705.     int        redraw;
  706. {
  707.     int            c;
  708.     int            oldState;
  709.     int            tmpState;
  710.  
  711.     if (redraw == TRUE)
  712.     must_redraw = CLEAR;
  713.  
  714.     /* If using ":silent cmd", don't wait for a return.  Also don't set
  715.      * need_wait_return to do it later. */
  716.     if (msg_silent != 0)
  717.     return;
  718.  
  719. /*
  720.  * With the global command (and some others) we only need one return at the
  721.  * end. Adjust cmdline_row to avoid the next message overwriting the last one.
  722.  * When inside vgetc(), we can't wait for a typed character at all.
  723.  */
  724.     if (vgetc_busy)
  725.     return;
  726.     if (no_wait_return)
  727.     {
  728.     need_wait_return = TRUE;
  729.     if (!exmode_active)
  730.         cmdline_row = msg_row;
  731.     return;
  732.     }
  733.  
  734.     redir_off = TRUE;            /* don't redirect this message */
  735.     oldState = State;
  736.     if (quit_more)
  737.     {
  738.     c = CR;                /* just pretend CR was hit */
  739.     quit_more = FALSE;
  740.     got_int = FALSE;
  741.     }
  742.     else if (exmode_active)
  743.     {
  744.     MSG_PUTS(" ");      /* make sure the cursor is on the right line */
  745.     c = CR;                /* no need for a return in ex mode */
  746.     got_int = FALSE;
  747.     }
  748.     else
  749.     {
  750.     State = HITRETURN;
  751. #ifdef FEAT_MOUSE
  752.     setmouse();
  753. #endif
  754. #ifdef USE_ON_FLY_SCROLL
  755.     dont_scroll = TRUE;        /* disallow scrolling here */
  756. #endif
  757.     hit_return_msg();
  758.  
  759. #ifdef ORG_HITRETURN
  760.     do
  761.     {
  762.         c = safe_vgetc();
  763.     } while (vim_strchr((char_u *)"\r\n: ", c) == NULL);
  764.     if (c == ':')            /* this can vi too (but not always!) */
  765.         stuffcharReadbuff(c);
  766. #else
  767.     do
  768.     {
  769.         c = safe_vgetc();
  770.         if (!global_busy)
  771.         got_int = FALSE;
  772. #ifdef FEAT_CLIPBOARD
  773.         /* Strange way to allow copying (yanking) a modeless selection at
  774.          * the hit-enter prompt.  Use CTRL-Y, because the same is used in
  775.          * Cmdline-mode and it's harmless when there is no selection. */
  776.         if (c == Ctrl_Y && clip_star.state == SELECT_DONE)
  777.         {
  778.         clip_copy_modeless_selection(TRUE);
  779.         c = K_IGNORE;
  780.         }
  781. #endif
  782.     } while (c == Ctrl_C || c == K_IGNORE
  783. #ifdef FEAT_GUI
  784.                 || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR
  785. #endif
  786. #ifdef FEAT_MOUSE
  787.                 || c == K_LEFTDRAG   || c == K_LEFTRELEASE
  788.                 || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
  789.                 || c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
  790.                 || c == K_MOUSEDOWN  || c == K_MOUSEUP
  791.                 || (!mouse_has(MOUSE_RETURN)
  792.                     && (c == K_LEFTMOUSE
  793.                     || c == K_MIDDLEMOUSE
  794.                     || c == K_RIGHTMOUSE))
  795. #endif
  796.                 );
  797.     ui_breakcheck();
  798. #ifdef FEAT_MOUSE
  799.     /*
  800.      * Avoid that the mouse-up event causes visual mode to start.
  801.      */
  802.     if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE)
  803.         (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
  804.     else
  805. #endif
  806.         if (vim_strchr((char_u *)"\r\n ", c) == NULL)
  807.     {
  808.         stuffcharReadbuff(c);
  809.         do_redraw = TRUE;        /* need a redraw even though there is
  810.                        something in the stuff buffer */
  811.     }
  812. #endif
  813.     }
  814.     redir_off = FALSE;
  815.  
  816.     /*
  817.      * If the user hits ':', '?' or '/' we get a command line from the next
  818.      * line.
  819.      */
  820.     if (c == ':' || c == '?' || c == '/')
  821.     {
  822.     if (!exmode_active)
  823.         cmdline_row = msg_row;
  824.     skip_redraw = TRUE;        /* skip redraw once */
  825.     do_redraw = FALSE;
  826.     }
  827.  
  828.     /*
  829.      * If the window size changed set_shellsize() will redraw the screen.
  830.      * Otherwise the screen is only redrawn if 'redraw' is set and no ':'
  831.      * typed.
  832.      */
  833.     tmpState = State;
  834.     State = oldState;            /* restore State before set_shellsize */
  835. #ifdef FEAT_MOUSE
  836.     setmouse();
  837. #endif
  838.     msg_check();
  839.  
  840.     /*
  841.      * When switching screens, we need to output an extra newline on exit.
  842.      */
  843. #if defined(UNIX) || defined(VMS)
  844.     if (swapping_screen() && !termcap_active)
  845.     newline_on_exit = TRUE;
  846. #endif
  847.  
  848.     need_wait_return = FALSE;
  849.     emsg_on_display = FALSE;    /* can delete error message now */
  850.     lines_left = -1;        /* reset lines_left at next msg_start() */
  851.     reset_last_sourcing();
  852.     if (keep_msg != NULL && vim_strsize(keep_msg) >=
  853.                   (Rows - cmdline_row - 1) * Columns + sc_col)
  854.     {
  855.     vim_free(keep_msg);
  856.     keep_msg = NULL;        /* don't redisplay message, it's too long */
  857.     }
  858.  
  859.     if (tmpState == SETWSIZE)        /* got resize event while in vgetc() */
  860.     {
  861.     starttermcap();            /* start termcap before redrawing */
  862.     shell_resized();
  863.     }
  864.     else if (!skip_redraw
  865.         && (redraw == TRUE || (msg_scrolled != 0 && redraw != -1)))
  866.     {
  867.     starttermcap();            /* start termcap before redrawing */
  868.     redraw_later(VALID);
  869.     }
  870. }
  871.  
  872. /*
  873.  * Write the hit-return prompt.
  874.  */
  875.     static void
  876. hit_return_msg()
  877. {
  878.     if (msg_didout)            /* start on a new line */
  879.     msg_putchar('\n');
  880.     if (got_int)
  881.     MSG_PUTS(_("Interrupt: "));
  882.  
  883. #ifdef ORG_HITRETURN
  884.     MSG_PUTS_ATTR(_("Hit ENTER to continue"), hl_attr(HLF_R));
  885. #else
  886.     MSG_PUTS_ATTR(_("Hit ENTER or type command to continue"), hl_attr(HLF_R));
  887. #endif
  888.     if (!msg_use_printf())
  889.     msg_clr_eos();
  890. }
  891.  
  892. /*
  893.  * Set "keep_msg" to "s".  Free the old value and check for NULL pointer.
  894.  */
  895.     void
  896. set_keep_msg(s)
  897.     char_u    *s;
  898. {
  899.     vim_free(keep_msg);
  900.     if (s != NULL && msg_silent == 0)
  901.     keep_msg = vim_strsave(s);
  902.     else
  903.     keep_msg = NULL;
  904. }
  905.  
  906. /*
  907.  * Prepare for outputting characters in the command line.
  908.  */
  909.     void
  910. msg_start()
  911. {
  912.     int        did_return = FALSE;
  913.  
  914.     vim_free(keep_msg);
  915.     keep_msg = NULL;            /* don't display old message now */
  916.     if (!msg_scroll && full_screen)    /* overwrite last message */
  917.     {
  918.     msg_row = cmdline_row;
  919.     msg_col = 0;
  920.     }
  921.     else if (msg_didout)            /* start message on next line */
  922.     {
  923.     msg_putchar('\n');
  924.     did_return = TRUE;
  925.     if (exmode_active != EXMODE_NORMAL)
  926.         cmdline_row = msg_row;
  927.     }
  928.     if (!msg_didany || lines_left < 0)
  929.     msg_starthere();
  930.     msg_didout = FALSE;                /* no output on current line yet */
  931.     cursor_off();
  932.  
  933.     /* when redirecting, may need to start a new line. */
  934.     if (!did_return)
  935.     redir_write((char_u *)"\n");
  936. }
  937.  
  938. /*
  939.  * Note that the current msg position is where messages start.
  940.  */
  941.     void
  942. msg_starthere()
  943. {
  944.     lines_left = cmdline_row;
  945.     msg_didany = FALSE;
  946. }
  947.  
  948.     void
  949. msg_putchar(c)
  950.     int        c;
  951. {
  952.     msg_putchar_attr(c, 0);
  953. }
  954.  
  955.     void
  956. msg_putchar_attr(c, attr)
  957.     int        c;
  958.     int        attr;
  959. {
  960.     char_u    buf[4];
  961.  
  962.     if (IS_SPECIAL(c))
  963.     {
  964.     buf[0] = K_SPECIAL;
  965.     buf[1] = K_SECOND(c);
  966.     buf[2] = K_THIRD(c);
  967.     buf[3] = NUL;
  968.     }
  969.     else
  970.     {
  971.     buf[0] = c;
  972.     buf[1] = NUL;
  973.     }
  974.     msg_puts_attr(buf, attr);
  975. }
  976.  
  977.     void
  978. msg_outnum(n)
  979.     long    n;
  980. {
  981.     char_u    buf[20];
  982.  
  983.     sprintf((char *)buf, "%ld", n);
  984.     msg_puts(buf);
  985. }
  986.  
  987.     void
  988. msg_home_replace(fname)
  989.     char_u    *fname;
  990. {
  991.     msg_home_replace_attr(fname, 0);
  992. }
  993.  
  994. #if defined(FEAT_FIND_ID) || defined(PROTO)
  995.     void
  996. msg_home_replace_hl(fname)
  997.     char_u    *fname;
  998. {
  999.     msg_home_replace_attr(fname, hl_attr(HLF_D));
  1000. }
  1001. #endif
  1002.  
  1003.     static void
  1004. msg_home_replace_attr(fname, attr)
  1005.     char_u  *fname;
  1006.     int        attr;
  1007. {
  1008.     char_u    *name;
  1009.  
  1010.     name = home_replace_save(NULL, fname);
  1011.     if (name != NULL)
  1012.     msg_outtrans_attr(name, attr);
  1013.     vim_free(name);
  1014. }
  1015.  
  1016. /*
  1017.  * Output 'len' characters in 'str' (including NULs) with translation
  1018.  * if 'len' is -1, output upto a NUL character.
  1019.  * Use attributes 'attr'.
  1020.  * Return the number of characters it takes on the screen.
  1021.  */
  1022.     int
  1023. msg_outtrans(str)
  1024.     char_u        *str;
  1025. {
  1026.     return msg_outtrans_attr(str, 0);
  1027. }
  1028.  
  1029.     int
  1030. msg_outtrans_attr(str, attr)
  1031.     char_u    *str;
  1032.     int        attr;
  1033. {
  1034.     return msg_outtrans_len_attr(str, (int)STRLEN(str), attr);
  1035. }
  1036.  
  1037.     int
  1038. msg_outtrans_len(str, len)
  1039.     char_u    *str;
  1040.     int        len;
  1041. {
  1042.     return msg_outtrans_len_attr(str, len, 0);
  1043. }
  1044.  
  1045. /*
  1046.  * Output one character at "p".  Return pointer to the next character.
  1047.  * Handles multi-byte characters.
  1048.  */
  1049.     char_u *
  1050. msg_outtrans_one(p, attr)
  1051.     char_u    *p;
  1052.     int        attr;
  1053. {
  1054. #ifdef FEAT_MBYTE
  1055.     int        l;
  1056.  
  1057.     if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
  1058.     {
  1059.     msg_outtrans_len_attr(p, l, attr);
  1060.     return p + l;
  1061.     }
  1062. #endif
  1063.     msg_puts_attr(transchar(*p), attr);
  1064.     return p + 1;
  1065. }
  1066.  
  1067.     int
  1068. msg_outtrans_len_attr(str, len, attr)
  1069.     char_u    *str;
  1070.     int        len;
  1071.     int        attr;
  1072. {
  1073.     int        retval = 0;
  1074.     char_u    *s;
  1075. #ifdef FEAT_MBYTE
  1076.     int        n;
  1077.     int        c;
  1078.     char_u    buf[MB_MAXBYTES + 1];
  1079. #endif
  1080.  
  1081.     /* if MSG_HIST flag set, add message to history */
  1082.     if (attr & MSG_HIST)
  1083.     {
  1084.     add_msg_hist(str, len, attr);
  1085.     attr &= ~MSG_HIST;
  1086.     }
  1087.  
  1088.     while (--len >= 0)
  1089.     {
  1090. #ifdef FEAT_MBYTE
  1091.     /* check multibyte; print it directly if it's printable.  */
  1092.     if (has_mbyte && (n = (*mb_ptr2len_check)(str)) > 1)
  1093.     {
  1094.         mch_memmove(buf, str, (size_t)n);
  1095.         buf[n] = NUL;
  1096.         c = (*mb_ptr2char)(buf);
  1097.         if (vim_isprintc(c))
  1098.         {
  1099.         msg_puts_attr(buf, attr);
  1100.         retval += (*mb_ptr2cells)(buf);
  1101.         }
  1102.         else
  1103.         {
  1104.         msg_puts_attr(transchar(c), attr == 0 ? hl_attr(HLF_8) : attr);
  1105.         retval += char2cells(c);
  1106.         }
  1107.         len -= n - 1;
  1108.         str += n;
  1109.     }
  1110.     else
  1111. #endif
  1112.     {
  1113.         s = transchar(*str);
  1114.         if (attr == 0 && s[1] != NUL)
  1115.         msg_puts_attr(s, hl_attr(HLF_8));    /* unprintable char */
  1116.         else
  1117.         msg_puts_attr(s, attr);
  1118.         retval += ptr2cells(str);
  1119.         ++str;
  1120.     }
  1121.     }
  1122.     return retval;
  1123. }
  1124.  
  1125. #if defined(FEAT_QUICKFIX) || defined(PROTO)
  1126.     void
  1127. msg_make(arg)
  1128.     char_u  *arg;
  1129. {
  1130.     int        i;
  1131.     static char_u *str = (char_u *)"eeffoc", *rs = (char_u *)"Plon#dqg#vxjduB";
  1132.  
  1133.     arg = skipwhite(arg);
  1134.     for (i = 5; *arg && i >= 0; --i)
  1135.     if (*arg++ != str[i])
  1136.         break;
  1137.     if (i < 0)
  1138.     {
  1139.     msg_putchar('\n');
  1140.     for (i = 0; rs[i]; ++i)
  1141.         msg_putchar(rs[i] - 3);
  1142.     }
  1143. }
  1144. #endif
  1145.  
  1146. /*
  1147.  * Output the string 'str' upto a NUL character.
  1148.  * Return the number of characters it takes on the screen.
  1149.  *
  1150.  * If K_SPECIAL is encountered, then it is taken in conjunction with the
  1151.  * following character and shown as <F1>, <S-Up> etc.  Any other character
  1152.  * which is not printable shown in <> form.
  1153.  * If 'from' is TRUE (lhs of a mapping), a space is shown as <Space>.
  1154.  * If a character is displayed in one of these special ways, is also
  1155.  * highlighted (its highlight name is '8' in the p_hl variable).
  1156.  * Otherwise characters are not highlighted.
  1157.  * This function is used to show mappings, where we want to see how to type
  1158.  * the character/string -- webb
  1159.  */
  1160.     int
  1161. msg_outtrans_special(str, from)
  1162.     char_u    *str;
  1163.     int        from;    /* TRUE for lhs of a mapping */
  1164. {
  1165.     int        retval = 0;
  1166.     char_u    *string;
  1167.     int        attr;
  1168.     int        len;
  1169.  
  1170.     attr = hl_attr(HLF_8);
  1171.     while (*str != NUL)
  1172.     {
  1173.     string = str2special(&str, from);
  1174.     len = vim_strsize(string);
  1175.     /* Highlight special keys */
  1176.     msg_puts_attr(string, len > 1
  1177. #ifdef FEAT_MBYTE
  1178.         && (*mb_ptr2len_check)(string) <= 1
  1179. #endif
  1180.         ? attr : 0);
  1181.     retval += len;
  1182.     }
  1183.     return retval;
  1184. }
  1185.  
  1186. /*
  1187.  * Return the printable string for the key codes at "*sp".
  1188.  * Used for translating the lhs or rhs of a mapping to printable chars.
  1189.  * Advances "sp" to the next code.
  1190.  */
  1191.     char_u *
  1192. str2special(sp, from)
  1193.     char_u    **sp;
  1194.     int        from;    /* TRUE for lhs of mapping */
  1195. {
  1196.     int            c;
  1197.     static char_u    buf[7];
  1198.     char_u        *str = *sp;
  1199.     int            modifiers = 0;
  1200.     int            special = FALSE;
  1201.  
  1202. #ifdef FEAT_MBYTE
  1203.     if (has_mbyte)
  1204.     {
  1205.     char_u    *p;
  1206.  
  1207.     /* Try to un-escape a multi-byte character.  Return the un-escaped
  1208.      * string if it is a multi-byte character. */
  1209.     p = mb_unescape(sp);
  1210.     if (p != NULL)
  1211.         return p;
  1212.     }
  1213. #endif
  1214.  
  1215.     c = *str;
  1216.     if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
  1217.     {
  1218.     if (str[1] == KS_MODIFIER)
  1219.     {
  1220.         modifiers = str[2];
  1221.         str += 3;
  1222.         c = *str;
  1223.     }
  1224.     if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL)
  1225.     {
  1226.         c = TO_SPECIAL(str[1], str[2]);
  1227.         str += 2;
  1228.         if (c == K_ZERO)    /* display <Nul> as ^@ */
  1229.         c = NUL;
  1230.     }
  1231.     if (IS_SPECIAL(c) || modifiers)    /* special key */
  1232.         special = TRUE;
  1233.     }
  1234.     *sp = str + 1;
  1235.  
  1236. #ifdef FEAT_MBYTE
  1237.     /* For multi-byte characters check for an illegal byte. */
  1238.     if (has_mbyte && MB_BYTE2LEN(*str) > (*mb_ptr2len_check)(str))
  1239.     {
  1240.     transchar_nonprint(buf, c);
  1241.     return buf;
  1242.     }
  1243. #endif
  1244.  
  1245.     /* Make unprintable characters in <> form, also <M-Space> and <Tab>.
  1246.      * Use <Space> only for lhs of a mapping. */
  1247.     if (special || char2cells(c) > 1 || (from && c == ' '))
  1248.     return get_special_key_name(c, modifiers);
  1249.     buf[0] = c;
  1250.     buf[1] = NUL;
  1251.     return buf;
  1252. }
  1253.  
  1254. /*
  1255.  * Translate a key sequence into special key names.
  1256.  */
  1257.     void
  1258. str2specialbuf(sp, buf, len)
  1259.     char_u    *sp;
  1260.     char_u    *buf;
  1261.     int        len;
  1262. {
  1263.     char_u    *s;
  1264.  
  1265.     *buf = NUL;
  1266.     while (*sp)
  1267.     {
  1268.     s = str2special(&sp, FALSE);
  1269.     if ((int)(STRLEN(s) + STRLEN(buf)) < len)
  1270.         STRCAT(buf, s);
  1271.     }
  1272. }
  1273.  
  1274. /*
  1275.  * print line for :print or :list command
  1276.  */
  1277.     void
  1278. msg_prt_line(s)
  1279.     char_u    *s;
  1280. {
  1281.     int        c;
  1282.     int        col = 0;
  1283.     int        n_extra = 0;
  1284.     int        c_extra = 0;
  1285.     char_u    *p_extra = NULL;        /* init to make SASC shut up */
  1286.     int        n;
  1287.     int        attr= 0;
  1288.     char_u    *trail = NULL;
  1289. #ifdef FEAT_MBYTE
  1290.     int        l;
  1291.     char_u    buf[MB_MAXBYTES + 1];
  1292. #endif
  1293.  
  1294.     /* find start of trailing whitespace */
  1295.     if (curwin->w_p_list && lcs_trail)
  1296.     {
  1297.     trail = s + STRLEN(s);
  1298.     while (trail > s && vim_iswhite(trail[-1]))
  1299.         --trail;
  1300.     }
  1301.  
  1302.     /* output a space for an empty line, otherwise the line will be
  1303.      * overwritten */
  1304.     if (*s == NUL && !curwin->w_p_list)
  1305.     msg_putchar(' ');
  1306.  
  1307.     for (;;)
  1308.     {
  1309.     if (n_extra)
  1310.     {
  1311.         --n_extra;
  1312.         if (c_extra)
  1313.         c = c_extra;
  1314.         else
  1315.         c = *p_extra++;
  1316.     }
  1317. #ifdef FEAT_MBYTE
  1318.     else if (has_mbyte && (l = (*mb_ptr2len_check)(s)) > 1)
  1319.     {
  1320.         col += (*mb_ptr2cells)(s);
  1321.         mch_memmove(buf, s, (size_t)l);
  1322.         buf[l] = NUL;
  1323.         msg_puts_attr(buf, attr);
  1324.         s += l;
  1325.         continue;
  1326.     }
  1327. #endif
  1328.     else
  1329.     {
  1330.         attr = 0;
  1331.         c = *s++;
  1332.         if (c == TAB && (!curwin->w_p_list || lcs_tab1))
  1333.         {
  1334.         /* tab amount depends on current column */
  1335.         n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1;
  1336.         if (!curwin->w_p_list)
  1337.         {
  1338.             c = ' ';
  1339.             c_extra = ' ';
  1340.         }
  1341.         else
  1342.         {
  1343.             c = lcs_tab1;
  1344.             c_extra = lcs_tab2;
  1345.             attr = hl_attr(HLF_8);
  1346.         }
  1347.         }
  1348.         else if (c == NUL && curwin->w_p_list && lcs_eol)
  1349.         {
  1350.         p_extra = (char_u *)"";
  1351.         c_extra = NUL;
  1352.         n_extra = 1;
  1353.         c = lcs_eol;
  1354.         attr = hl_attr(HLF_AT);
  1355.         --s;
  1356.         }
  1357.         else if (c != NUL && (n = byte2cells(c)) > 1)
  1358.         {
  1359.         n_extra = n - 1;
  1360.         p_extra = transchar(c);
  1361.         c_extra = NUL;
  1362.         c = *p_extra++;
  1363.         }
  1364.         else if (c == ' ' && trail != NULL && s > trail)
  1365.         {
  1366.         c = lcs_trail;
  1367.         attr = hl_attr(HLF_8);
  1368.         }
  1369.     }
  1370.  
  1371.     if (c == NUL)
  1372.         break;
  1373.  
  1374.     msg_putchar_attr(c, attr);
  1375.     col++;
  1376.     }
  1377.     msg_clr_eos();
  1378. }
  1379.  
  1380. #ifdef FEAT_MBYTE
  1381. /*
  1382.  * Use screen_puts() to output one multi-byte character.
  1383.  * Return the pointer "s" advanced to the next character.
  1384.  */
  1385.     static char_u *
  1386. screen_puts_mbyte(s, l, attr)
  1387.     char_u    *s;
  1388.     int        l;
  1389.     int        attr;
  1390. {
  1391.     int        cw;
  1392.     char_u    buf[MB_MAXBYTES + 1];
  1393.  
  1394.     msg_didout = TRUE;        /* remember that line is not empty */
  1395.     cw = (*mb_ptr2cells)(s);
  1396.     if (cw > 1 && msg_col == Columns - 1)
  1397.     {
  1398.     /* Doesn't fit, print a highlighted '>' to fill it up. */
  1399.     msg_screen_putchar('>', hl_attr(HLF_AT));
  1400.     return s;
  1401.     }
  1402.  
  1403.     mch_memmove(buf, s, (size_t)l);
  1404.     buf[l] = NUL;
  1405.     screen_puts(buf, msg_row, msg_col, attr);
  1406.     if ((msg_col += cw) >= Columns)
  1407.     {
  1408.     msg_col = 0;
  1409.     ++msg_row;
  1410.     }
  1411.     return s + l;
  1412. }
  1413. #endif
  1414.  
  1415. /*
  1416.  * Output a string to the screen at position msg_row, msg_col.
  1417.  * Update msg_row and msg_col for the next message.
  1418.  */
  1419.     void
  1420. msg_puts(s)
  1421.     char_u    *s;
  1422. {
  1423.     msg_puts_attr(s, 0);
  1424. }
  1425.  
  1426.     void
  1427. msg_puts_title(s)
  1428.     char_u    *s;
  1429. {
  1430.     msg_puts_attr(s, hl_attr(HLF_T));
  1431. }
  1432.  
  1433. #if defined(FEAT_CSCOPE) || defined(PROTO)
  1434. /*
  1435.  * if printing a string will exceed the screen width, print "..." in the
  1436.  * middle.
  1437.  */
  1438.     void
  1439. msg_puts_long(longstr)
  1440.     char_u    *longstr;
  1441. {
  1442.     msg_puts_long_len_attr(longstr, (int)strlen((char *)longstr), 0);
  1443. }
  1444. #endif
  1445.  
  1446. /*
  1447.  * Show a message in such a way that it always fits in the line.  Cut out a
  1448.  * part in the middle and replace it with "..." when necessary.
  1449.  */
  1450.     void
  1451. msg_puts_long_attr(longstr, attr)
  1452.     char_u    *longstr;
  1453.     int        attr;
  1454. {
  1455.     msg_puts_long_len_attr(longstr, (int)strlen((char *)longstr), attr);
  1456. }
  1457.  
  1458.     void
  1459. msg_puts_long_len_attr(longstr, len, attr)
  1460.     char_u    *longstr;
  1461.     int        len;
  1462.     int        attr;
  1463. {
  1464.     int        slen = len;
  1465.     int        room;
  1466.  
  1467.     room = Columns - msg_col;
  1468.     if (len > room && room >= 20)
  1469.     {
  1470.     slen = (room - 3) / 2;
  1471.     msg_outtrans_len_attr(longstr, slen, attr);
  1472.     msg_puts_attr((char_u *)"...", hl_attr(HLF_8));
  1473.     }
  1474.     msg_outtrans_len_attr(longstr + len - slen, slen, attr);
  1475. }
  1476.  
  1477. /*
  1478.  * Basic function for writing a message with highlight attributes.
  1479.  */
  1480.     void
  1481. msg_puts_attr(s, attr)
  1482.     char_u    *s;
  1483.     int        attr;
  1484. {
  1485.     int        oldState;
  1486.     char_u    *p;
  1487.     char_u    buf[4];
  1488. #ifdef FEAT_MBYTE
  1489.     int        l;
  1490. #endif
  1491.     int        c;
  1492.  
  1493.     /*
  1494.      * If redirection is on, also write to the redirection file.
  1495.      */
  1496.     redir_write(s);
  1497.  
  1498.     /*
  1499.      * Don't print anything when using ":silent cmd".
  1500.      */
  1501.     if (msg_silent != 0)
  1502.     return;
  1503.  
  1504.     /* if MSG_HIST flag set, add message to history */
  1505.     if (attr & MSG_HIST)
  1506.     {
  1507.     add_msg_hist(s, -1, attr);
  1508.     attr &= ~MSG_HIST;
  1509.     }
  1510.  
  1511.     /*
  1512.      * When writing something to the screen after it has scrolled, requires a
  1513.      * wait-return prompt later.  Needed when scrolling, resetting
  1514.      * need_wait_return after some prompt, and then outputting something
  1515.      * without scrolling
  1516.      */
  1517.     if (msg_scrolled && !msg_scrolled_ign)
  1518.     need_wait_return = TRUE;
  1519.  
  1520.     /*
  1521.      * If there is no valid screen, use fprintf so we can see error messages.
  1522.      * If termcap is not active, we may be writing in an alternate console
  1523.      * window, cursor positioning may not work correctly (window size may be
  1524.      * different, e.g. for Win32 console) or we just don't know where the
  1525.      * cursor is.
  1526.      */
  1527.     if (msg_use_printf())
  1528.     {
  1529. #ifdef WIN3264
  1530.     if (!silent_mode)
  1531.         mch_settmode(TMODE_COOK);    /* handle '\r' and '\n' correctly */
  1532. #endif
  1533.     while (*s)
  1534.     {
  1535.         if (!silent_mode)
  1536.         {
  1537.         p = &buf[0];
  1538.         /* NL --> CR NL translation (for Unix) */
  1539.         /* NL --> CR translation (for Mac) */
  1540.         if (*s == '\n')
  1541.             *p++ = '\r';
  1542. #ifdef USE_CR
  1543.         else
  1544. #endif
  1545.             *p++ = *s;
  1546.         *p = '\0';
  1547.         mch_errmsg((char *)buf);
  1548.         }
  1549.  
  1550.         /* primitive way to compute the current column */
  1551.         if (*s == '\r' || *s == '\n')
  1552.         msg_col = 0;
  1553.         else
  1554.         ++msg_col;
  1555.         ++s;
  1556.     }
  1557.     msg_didout = TRUE;        /* assume that line is not empty */
  1558.  
  1559. #ifdef WIN3264
  1560.     if (!silent_mode)
  1561.         mch_settmode(TMODE_RAW);
  1562. #endif
  1563.     return;
  1564.     }
  1565.  
  1566.     msg_didany = TRUE;        /* remember that something was outputted */
  1567.     while (*s)
  1568.     {
  1569.     /*
  1570.      * The screen is scrolled up when:
  1571.      * - When outputting a newline in the last row
  1572.      * - when outputting a character in the last column of the last row
  1573.      *   (some terminals scroll automatically, some don't. To avoid
  1574.      *   problems we scroll ourselves)
  1575.      */
  1576.     if (msg_row >= Rows - 1
  1577.         && (*s == '\n'
  1578.             || msg_col >= Columns - 1
  1579.             || (*s == TAB && msg_col >= ((Columns - 1) & ~7))
  1580. #ifdef FEAT_MBYTE
  1581.             || (has_mbyte && (*mb_ptr2cells)(s) > 1
  1582.                             && msg_col >= Columns - 2)
  1583. #endif
  1584.                   ))
  1585.     {
  1586.         /* When no more prompt an no more room, truncate here */
  1587.         if (msg_no_more && lines_left == 0)
  1588.         break;
  1589. #ifdef FEAT_GUI
  1590.         /* Remove the cursor before scrolling, ScreenLines[] is going to
  1591.          * become invalid. */
  1592.         if (gui.in_use)
  1593.         gui_undraw_cursor();
  1594. #endif
  1595.         /* scrolling up always works */
  1596.         screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL);
  1597.  
  1598.         if (!can_clear((char_u *)" "))
  1599.         {
  1600.         /* Scrolling up doesn't result in the right background.  Set
  1601.          * the background here.  It's not efficient, but avoids that
  1602.          * we have to do it all over the code. */
  1603.         screen_fill((int)Rows - 1, (int)Rows, 0,
  1604.                            (int)Columns, ' ', ' ', 0);
  1605.  
  1606.         /* Also clear the last char of the last but one line if it was
  1607.          * not cleared before to avoid a scroll-up. */
  1608.         if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1]
  1609.                                    == (sattr_T)-1)
  1610.             screen_fill((int)Rows - 2, (int)Rows - 1,
  1611.                  (int)Columns - 1, (int)Columns, ' ', ' ', 0);
  1612.         }
  1613.  
  1614.         msg_row = Rows - 2;
  1615.         if (msg_col >= Columns)    /* can happen after screen resize */
  1616.         msg_col = Columns - 1;
  1617.  
  1618.         ++msg_scrolled;
  1619.         need_wait_return = TRUE;    /* may need wait_return in main() */
  1620.         if (must_redraw < VALID)
  1621.         must_redraw = VALID;
  1622.         redraw_cmdline = TRUE;
  1623.         if (cmdline_row > 0 && !exmode_active)
  1624.         --cmdline_row;
  1625.  
  1626.         /*
  1627.          * if screen is completely filled wait for a character
  1628.          */
  1629.         if (p_more && --lines_left == 0 && State != HITRETURN
  1630.                         && !msg_no_more && !exmode_active)
  1631.         {
  1632.         oldState = State;
  1633.         State = ASKMORE;
  1634. #ifdef FEAT_MOUSE
  1635.         setmouse();
  1636. #endif
  1637.         msg_moremsg(FALSE);
  1638.         for (;;)
  1639.         {
  1640.             /*
  1641.              * Get a typed character directly from the user.
  1642.              */
  1643.             c = get_keystroke();
  1644.  
  1645. #if defined(FEAT_MENU) && defined(FEAT_GUI)
  1646.             if (c == K_MENU)
  1647.             {
  1648.             int idx = get_menu_index(current_menu, ASKMORE);
  1649.  
  1650.             /* Used a menu.  If it starts with CTRL-Y, it must
  1651.              * be a "Copy" for the clipboard.  Otherwise
  1652.              * assume that we end */
  1653.             if (idx == MENU_INDEX_INVALID)
  1654.                 continue;
  1655.             c = *current_menu->strings[idx];
  1656.             if (c != NUL && current_menu->strings[idx][1] != NUL)
  1657.                 ins_typebuf(current_menu->strings[idx] + 1,
  1658.                     current_menu->noremap[idx], 0, TRUE,
  1659.                     current_menu->silent[idx]);
  1660.             }
  1661. #endif
  1662.  
  1663.             switch (c)
  1664.             {
  1665.             case BS:
  1666.             case 'k':
  1667.             case K_UP:
  1668.             if (!more_back_used)
  1669.             {
  1670.                 msg_moremsg(TRUE);
  1671.                 continue;
  1672.             }
  1673.             more_back = 1;
  1674.             lines_left = 1;
  1675.             break;
  1676.             case CR:        /* one extra line */
  1677.             case NL:
  1678.             case 'j':
  1679.             case K_DOWN:
  1680.             lines_left = 1;
  1681.             break;
  1682.             case ':':        /* start new command line */
  1683.             /* Since got_int is set all typeahead will be flushed,
  1684.              * but we want to keep this ':', remember that in a
  1685.              * special way. */
  1686.             typeahead_noflush(':');
  1687.             cmdline_row = Rows - 1;      /* put ':' on this line */
  1688.             skip_redraw = TRUE;      /* skip redraw once */
  1689.             need_wait_return = FALSE; /* don't wait in main() */
  1690.             /*FALLTHROUGH*/
  1691.             case 'q':        /* quit */
  1692.             case Ctrl_C:
  1693.             case ESC:
  1694. #ifdef FEAT_CON_DIALOG
  1695.             if (msg_noquit_more)
  1696.             {
  1697.                 /* When quitting is not possible, behave like
  1698.                  * another page can be printed */
  1699.                 lines_left = Rows - 1;
  1700.             }
  1701.             else
  1702. #endif
  1703.             {
  1704.                 got_int = TRUE;
  1705.                 quit_more = TRUE;
  1706.             }
  1707.             break;
  1708.             case 'u':        /* Up half a page */
  1709.             case K_PAGEUP:
  1710.             if (!more_back_used)
  1711.             {
  1712.                 msg_moremsg(TRUE);
  1713.                 continue;
  1714.             }
  1715.             more_back = Rows / 2;
  1716.             /*FALLTHROUGH*/
  1717.             case 'd':        /* Down half a page */
  1718.             lines_left = Rows / 2;
  1719.             break;
  1720.             case 'b':        /* one page back */
  1721.             if (!more_back_used)
  1722.             {
  1723.                 msg_moremsg(TRUE);
  1724.                 continue;
  1725.             }
  1726.             more_back = Rows - 1;
  1727.             /*FALLTHROUGH*/
  1728.             case ' ':        /* one extra page */
  1729.             case K_PAGEDOWN:
  1730.             lines_left = Rows - 1;
  1731.             break;
  1732.  
  1733. #ifdef FEAT_CLIPBOARD
  1734.             case Ctrl_Y:
  1735.             /* Strange way to allow copying (yanking) a modeless
  1736.              * selection at the more prompt.  Use CTRL-Y,
  1737.              * because the same is used in Cmdline-mode and at the
  1738.              * hit-enter prompt.  However, scrolling one line up
  1739.              * might be expected... */
  1740.             if (clip_star.state == SELECT_DONE)
  1741.                 clip_copy_modeless_selection(TRUE);
  1742.             continue;
  1743. #endif
  1744.             default:        /* no valid response */
  1745.             msg_moremsg(TRUE);
  1746.             continue;
  1747.             }
  1748.             break;
  1749.         }
  1750.  
  1751.         /* clear the --more-- message */
  1752.         screen_fill((int)Rows - 1, (int)Rows,
  1753.                         0, (int)Columns, ' ', ' ', 0);
  1754.         State = oldState;
  1755. #ifdef FEAT_MOUSE
  1756.         setmouse();
  1757. #endif
  1758.         if (quit_more)
  1759.         {
  1760.             msg_row = Rows - 1;
  1761.             msg_col = 0;
  1762.             return;        /* the string is not displayed! */
  1763.         }
  1764.         }
  1765.     }
  1766.     if (*s == '\n')            /* go to next line */
  1767.     {
  1768.         msg_didout = FALSE;        /* remember that line is empty */
  1769.         msg_col = 0;
  1770.         if (++msg_row >= Rows)  /* safety check */
  1771.         msg_row = Rows - 1;
  1772.     }
  1773.     else if (*s == '\r')        /* go to column 0 */
  1774.     {
  1775.         msg_col = 0;
  1776.     }
  1777.     else if (*s == '\b')        /* go to previous char */
  1778.     {
  1779.         if (msg_col)
  1780.         --msg_col;
  1781.     }
  1782.     else if (*s == TAB)        /* translate into spaces */
  1783.     {
  1784.         do
  1785.         msg_screen_putchar(' ', attr);
  1786.         while (msg_col & 7);
  1787.     }
  1788. #ifdef FEAT_MBYTE
  1789.     else if (has_mbyte && (l = (*mb_ptr2len_check)(s)) > 1)
  1790.         s = screen_puts_mbyte(s, l, attr) - 1;
  1791. #endif
  1792.     else
  1793.         msg_screen_putchar(*s, attr);
  1794.     ++s;
  1795.     }
  1796.     msg_check();
  1797. }
  1798.  
  1799. /*
  1800.  * Returns TRUE when messages should be printed with mch_errmsg().
  1801.  * This is used when there is no valid screen, so we can see error messages.
  1802.  * If termcap is not active, we may be writing in an alternate console
  1803.  * window, cursor positioning may not work correctly (window size may be
  1804.  * different, e.g. for Win32 console) or we just don't know where the
  1805.  * cursor is.
  1806.  */
  1807.     static int
  1808. msg_use_printf()
  1809. {
  1810.     return (!msg_check_screen()
  1811. #if defined(WIN3264) && !defined(FEAT_GUI_MSWIN)
  1812.         || !termcap_active
  1813. #endif
  1814.         || (swapping_screen() && !termcap_active)
  1815.            );
  1816. }
  1817.  
  1818. #if defined(USE_MCH_ERRMSG) || defined(PROTO)
  1819.  
  1820. #ifdef mch_errmsg
  1821. # undef mch_errmsg
  1822. #endif
  1823. #ifdef mch_msg
  1824. # undef mch_msg
  1825. #endif
  1826.  
  1827. /*
  1828.  * collect error messages until the GUI has started and they can be
  1829.  * displayed in a message box.
  1830.  */
  1831.     void
  1832. mch_errmsg(str)
  1833.     char    *str;
  1834. {
  1835.     int        len;
  1836.  
  1837. #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
  1838.     /* On Unix use stderr if it's a tty.
  1839.      * When not going to start the GUI also use stderr. */
  1840.     if (
  1841. # ifdef UNIX
  1842.         isatty(2)
  1843. #  ifdef FEAT_GUI
  1844.         ||
  1845. #  endif
  1846. # endif
  1847. # ifdef FEAT_GUI
  1848.         !(gui.in_use || gui.starting)
  1849. # endif
  1850.         )
  1851.     {
  1852.     fprintf(stderr, "%s", str);
  1853.     return;
  1854.     }
  1855. #endif
  1856.  
  1857.     /* avoid a delay for a message that isn't there */
  1858.     emsg_on_display = FALSE;
  1859.  
  1860.     len = (int)STRLEN(str) + 1;
  1861.     if (error_ga.ga_growsize == 0)
  1862.     {
  1863.     error_ga.ga_growsize = 80;
  1864.     error_ga.ga_itemsize = 1;
  1865.     }
  1866.     if (ga_grow(&error_ga, len) == OK)
  1867.     {
  1868.     mch_memmove((char_u *)error_ga.ga_data + error_ga.ga_len,
  1869.                               (char_u *)str, len);
  1870. #ifdef UNIX
  1871.     /* remove CR characters, they are displayed */
  1872.     {
  1873.         char_u    *p;
  1874.  
  1875.         p = (char_u *)error_ga.ga_data + error_ga.ga_len;
  1876.         for (;;)
  1877.         {
  1878.         p = vim_strchr(p, '\r');
  1879.         if (p == NULL)
  1880.             break;
  1881.         *p = ' ';
  1882.         }
  1883.     }
  1884. #endif
  1885.     --len;        /* don't count the NUL at the end */
  1886.     error_ga.ga_len += len;
  1887.     error_ga.ga_room -= len;
  1888.     }
  1889. }
  1890.  
  1891.     void
  1892. mch_msg(str)
  1893.     char    *str;
  1894. {
  1895. #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
  1896.     /* On Unix use stdout if we have a tty.  This allows "vim -h | more" and
  1897.      * uses mch_errmsg() when started from the desktop.
  1898.      * When not going to start the GUI also use stdout. */
  1899.     if (
  1900. #  ifdef UNIX
  1901.         isatty(2)
  1902. #   ifdef FEAT_GUI
  1903.         ||
  1904. #   endif
  1905. #  endif
  1906. #  ifdef FEAT_GUI
  1907.         !(gui.in_use || gui.starting)
  1908. #  endif
  1909.         )
  1910.     {
  1911.     printf("%s", str);
  1912.     return;
  1913.     }
  1914. # endif
  1915.     mch_errmsg(str);
  1916. }
  1917. #endif /* USE_MCH_ERRMSG */
  1918.  
  1919.     static void
  1920. msg_screen_putchar(c, attr)
  1921.     int        c;
  1922.     int        attr;
  1923. {
  1924.     msg_didout = TRUE;        /* remember that line is not empty */
  1925.     screen_putchar(c, msg_row, msg_col, attr);
  1926.     if (++msg_col >= Columns)
  1927.     {
  1928.     msg_col = 0;
  1929.     ++msg_row;
  1930.     }
  1931. }
  1932.  
  1933.     void
  1934. msg_moremsg(full)
  1935.     int        full;
  1936. {
  1937.     int        attr;
  1938.  
  1939.     attr = hl_attr(HLF_M);
  1940.     screen_puts((char_u *)_("-- More --"), (int)Rows - 1, 0, attr);
  1941.     if (full)
  1942.     screen_puts(more_back_used
  1943.         ? (char_u *)_(" (RET/BS: line, SPACE/b: page, d/u: half page, q: quit)")
  1944.         : (char_u *)_(" (RET: line, SPACE: page, d: half page, q: quit)"),
  1945.         (int)Rows - 1, 10, attr);
  1946. }
  1947.  
  1948. /*
  1949.  * Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or
  1950.  * exmode_active.
  1951.  */
  1952.     void
  1953. repeat_message()
  1954. {
  1955.     if (State == ASKMORE)
  1956.     {
  1957.     msg_moremsg(TRUE);    /* display --more-- message again */
  1958.     msg_row = Rows - 1;
  1959.     }
  1960. #ifdef FEAT_CON_DIALOG
  1961.     else if (State == CONFIRM)
  1962.     {
  1963.     display_confirm_msg();    /* display ":confirm" message again */
  1964.     msg_row = Rows - 1;
  1965.     }
  1966. #endif
  1967.     else if (State == EXTERNCMD)
  1968.     {
  1969.     windgoto(msg_row, msg_col); /* put cursor back */
  1970.     }
  1971.     else if (State == HITRETURN || State == SETWSIZE)
  1972.     {
  1973.     hit_return_msg();
  1974.     msg_row = Rows - 1;
  1975.     }
  1976. }
  1977.  
  1978. /*
  1979.  * msg_check_screen - check if the screen is initialized.
  1980.  * Also check msg_row and msg_col, if they are too big it may cause a crash.
  1981.  * While starting the GUI the terminal codes will be set for the GUI, but the
  1982.  * output goes to the terminal.  Don't use the terminal codes then.
  1983.  */
  1984.     static int
  1985. msg_check_screen()
  1986. {
  1987.     if (!full_screen || !screen_valid(FALSE))
  1988.     return FALSE;
  1989.  
  1990.     if (msg_row >= Rows)
  1991.     msg_row = Rows - 1;
  1992.     if (msg_col >= Columns)
  1993.     msg_col = Columns - 1;
  1994.     return TRUE;
  1995. }
  1996.  
  1997. /*
  1998.  * Clear from current message position to end of screen.
  1999.  * Note: msg_col is not updated, so we remember the end of the message
  2000.  * for msg_check().
  2001.  */
  2002.     void
  2003. msg_clr_eos()
  2004. {
  2005.     if (msg_use_printf())
  2006.     {
  2007.     if (full_screen)    /* only when termcap codes are valid */
  2008.     {
  2009.         if (*T_CD)
  2010.         out_str(T_CD);    /* clear to end of display */
  2011.         else if (*T_CE)
  2012.         out_str(T_CE);    /* clear to end of line */
  2013.     }
  2014.     }
  2015.     else
  2016.     {
  2017.     screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ', 0);
  2018.     screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
  2019.     }
  2020. }
  2021.  
  2022. /*
  2023.  * Clear the command line.
  2024.  */
  2025.     void
  2026. msg_clr_cmdline()
  2027. {
  2028.     msg_row = cmdline_row;
  2029.     msg_col = 0;
  2030.     msg_clr_eos();
  2031. }
  2032.  
  2033. /*
  2034.  * end putting a message on the screen
  2035.  * call wait_return if the message does not fit in the available space
  2036.  * return TRUE if wait_return not called.
  2037.  */
  2038.     int
  2039. msg_end()
  2040. {
  2041.     /*
  2042.      * if the string is larger than the window,
  2043.      * or the ruler option is set and we run into it,
  2044.      * we have to redraw the window.
  2045.      * Do not do this if we are abandoning the file or editing the command line.
  2046.      */
  2047.     if (!exiting && need_wait_return && !(State & CMDLINE))
  2048.     {
  2049.     wait_return(FALSE);
  2050.     return FALSE;
  2051.     }
  2052.     out_flush();
  2053.     return TRUE;
  2054. }
  2055.  
  2056. /*
  2057.  * If the written message runs into the shown command or ruler, we have to
  2058.  * wait for hit-return and redraw the window later.
  2059.  */
  2060.     void
  2061. msg_check()
  2062. {
  2063.     if (msg_row == Rows - 1 && msg_col >= sc_col)
  2064.     {
  2065.     need_wait_return = TRUE;
  2066.     redraw_cmdline = TRUE;
  2067.     }
  2068. }
  2069.  
  2070. /*
  2071.  * May write a string to the redirection file.
  2072.  */
  2073.     static void
  2074. redir_write(s)
  2075.     char_u    *s;
  2076. {
  2077.     static int        cur_col = 0;
  2078.  
  2079.     if ((redir_fd != NULL
  2080. #ifdef FEAT_EVAL
  2081.               || redir_reg
  2082. #endif
  2083.                        ) && !redir_off)
  2084.     {
  2085.     /* If the string doesn't start with CR or NL, go to msg_col */
  2086.     if (*s != '\n' && *s != '\r')
  2087.     {
  2088.         while (cur_col < msg_col)
  2089.         {
  2090. #ifdef FEAT_EVAL
  2091.         if (redir_reg)
  2092.             write_reg_contents(redir_reg, (char_u *)" ", TRUE);
  2093.         else if (redir_fd)
  2094. #endif
  2095.             fputs(" ", redir_fd);
  2096.         ++cur_col;
  2097.         }
  2098.     }
  2099.  
  2100. #ifdef FEAT_EVAL
  2101.     if (redir_reg)
  2102.         write_reg_contents(redir_reg, s, TRUE);
  2103.     else if (redir_fd)
  2104. #endif
  2105.         fputs((char *)s, redir_fd);
  2106.  
  2107.     /* Adjust the current column */
  2108.     while (*s)
  2109.     {
  2110.         if (*s == '\r' || *s == '\n')
  2111.         cur_col = 0;
  2112.         else if (*s == '\t')
  2113.         cur_col += (8 - cur_col % 8);
  2114.         else
  2115.         ++cur_col;
  2116.         ++s;
  2117.     }
  2118.     }
  2119. }
  2120.  
  2121. /*
  2122.  * Give a warning message (for searching).
  2123.  * Use 'w' highlighting and may repeat the message after redrawing
  2124.  */
  2125.     void
  2126. give_warning(message, hl)
  2127.     char_u  *message;
  2128.     int        hl;
  2129. {
  2130.     /* Don't do this for ":silent". */
  2131.     if (msg_silent != 0)
  2132.     return;
  2133.  
  2134. #ifdef FEAT_EVAL
  2135.     set_vim_var_string(VV_WARNINGMSG, message, -1);
  2136. #endif
  2137. #ifdef VIMBUDDY
  2138.     VimBuddyText(message, 1);
  2139. #else
  2140.     vim_free(keep_msg);
  2141.     keep_msg = NULL;
  2142.     if (hl)
  2143.     keep_msg_attr = hl_attr(HLF_W);
  2144.     else
  2145.     keep_msg_attr = 0;
  2146.     if (msg_attr(message, keep_msg_attr) && msg_scrolled == 0)
  2147.     set_keep_msg(message);
  2148.     msg_didout = FALSE;        /* overwrite this message */
  2149.     msg_nowait = TRUE;        /* don't wait for this message */
  2150.     msg_col = 0;
  2151. #endif
  2152. }
  2153.  
  2154. /*
  2155.  * Advance msg cursor to column "col".
  2156.  */
  2157.     void
  2158. msg_advance(col)
  2159.     int        col;
  2160. {
  2161.     if (msg_silent != 0)    /* nothing to advance to */
  2162.     {
  2163.     msg_putchar(' ');    /* insert something for redirection */
  2164.     return;
  2165.     }
  2166.     if (col >= Columns)        /* not enough room */
  2167.     col = Columns - 1;
  2168.     while (msg_col < col)
  2169.     msg_putchar(' ');
  2170. }
  2171.  
  2172. #if defined(FEAT_CON_DIALOG) || defined(PROTO)
  2173. /*
  2174.  * Used for "confirm()" function, and the :confirm command prefix.
  2175.  * Versions which haven't got flexible dialogs yet, and console
  2176.  * versions, get this generic handler which uses the command line.
  2177.  *
  2178.  * type  = one of:
  2179.  *       VIM_QUESTION, VIM_INFO, VIM_WARNING, VIM_ERROR or VIM_GENERIC
  2180.  * title = title string (can be NULL for default)
  2181.  * (neither used in console dialogs at the moment)
  2182.  *
  2183.  * Format of the "buttons" string:
  2184.  * "Button1Name\nButton2Name\nButton3Name"
  2185.  * The first button should normally be the default/accept
  2186.  * The second button should be the 'Cancel' button
  2187.  * Other buttons- use your imagination!
  2188.  * A '&' in a button name becomes a shortcut, so each '&' should be before a
  2189.  * different letter.
  2190.  */
  2191. /* ARGSUSED */
  2192.     int
  2193. do_dialog(type, title, message, buttons, dfltbutton, textfield)
  2194.     int        type;
  2195.     char_u    *title;
  2196.     char_u    *message;
  2197.     char_u    *buttons;
  2198.     int        dfltbutton;
  2199.     char_u    *textfield;    /* IObuff for inputdialog(), NULL otherwise */
  2200. {
  2201.     int        oldState;
  2202.     int        retval = 0;
  2203.     char_u    *hotkeys;
  2204.     int        c;
  2205.  
  2206. #ifndef NO_CONSOLE
  2207.     /* Don't output anything in silent mode ("ex -s") */
  2208.     if (silent_mode)
  2209.     return dfltbutton;   /* return default option */
  2210. #endif
  2211.  
  2212. #ifdef FEAT_GUI_DIALOG
  2213.     /* When GUI is running, use the GUI dialog */
  2214.     if (gui.in_use)
  2215.     {
  2216.     c = gui_mch_dialog(type, title, message, buttons, dfltbutton,
  2217.                                    textfield);
  2218.     msg_end_prompt();
  2219.     return c;
  2220.     }
  2221. #endif
  2222.  
  2223.     oldState = State;
  2224.     State = CONFIRM;
  2225. #ifdef FEAT_MOUSE
  2226.     setmouse();
  2227. #endif
  2228.  
  2229.     /*
  2230.      * Since we wait for a keypress, don't make the
  2231.      * user press RETURN as well afterwards.
  2232.      */
  2233.     ++no_wait_return;
  2234.     hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
  2235.  
  2236.     if (hotkeys != NULL)
  2237.     {
  2238.     for (;;)
  2239.     {
  2240.         /* Get a typed character directly from the user. */
  2241.         c = get_keystroke();
  2242.         switch (c)
  2243.         {
  2244.         case CR:        /* User accepts default option */
  2245.         case NL:
  2246.         retval = dfltbutton;
  2247.         break;
  2248.         case Ctrl_C:        /* User aborts/cancels */
  2249.         case ESC:
  2250.         retval = 0;
  2251.         break;
  2252.         default:        /* Could be a hotkey? */
  2253.         if (c > 255)    /* special keys are ignored here */
  2254.             continue;
  2255.         for (retval = 0; hotkeys[retval]; retval++)
  2256.         {
  2257.             if (hotkeys[retval] == TO_LOWER(c))
  2258.             break;
  2259.         }
  2260.         if (hotkeys[retval])
  2261.         {
  2262.             retval++;
  2263.             break;
  2264.         }
  2265.         /* No hotkey match, so keep waiting */
  2266.         continue;
  2267.         }
  2268.         break;
  2269.     }
  2270.  
  2271.     vim_free(hotkeys);
  2272.     }
  2273.  
  2274.     State = oldState;
  2275. #ifdef FEAT_MOUSE
  2276.     setmouse();
  2277. #endif
  2278.     --no_wait_return;
  2279.     msg_end_prompt();
  2280.  
  2281.     return retval;
  2282. }
  2283.  
  2284. char_u    *confirm_msg = NULL;        /* ":confirm" message */
  2285.  
  2286. /*
  2287.  * Format the dialog string, and display it at the bottom of
  2288.  * the screen. Return a string of hotkey chars (if defined) for
  2289.  * each 'button'. If a button has no hotkey defined, the string
  2290.  * has the buttons first letter.
  2291.  *
  2292.  * Returns allocated array, or NULL for error.
  2293.  *
  2294.  */
  2295.     static char_u *
  2296. msg_show_console_dialog(message, buttons, dfltbutton)
  2297.     char_u    *message;
  2298.     char_u    *buttons;
  2299.     int        dfltbutton;
  2300. {
  2301.     int        len = 0;
  2302.     int        lenhotkey = 1;    /*first button*/
  2303.     char_u    *hotk;
  2304.     char_u    *p;
  2305.     char_u    *q;
  2306.     char_u    *r;
  2307.  
  2308.     /*
  2309.      * First compute how long a string we need to allocate for the message.
  2310.      */
  2311.     r = buttons;
  2312.     while (*r)
  2313.     {
  2314.     if (*r == DLG_BUTTON_SEP)
  2315.     {
  2316.         len++;        /* '\n' -> ', ' */
  2317.         lenhotkey++;    /* each button needs a hotkey */
  2318.     }
  2319.     else if (*r == DLG_HOTKEY_CHAR)
  2320.     {
  2321.         len++;        /* '&a' -> '[a]' */
  2322.     }
  2323.     r++;
  2324.     }
  2325.  
  2326.     len += STRLEN(message)
  2327.         + 2            /* for the NL's */
  2328.         + STRLEN(buttons)
  2329.         + 3;        /* for the ": " and NUL */
  2330.  
  2331.     lenhotkey++;        /* for the NUL */
  2332.  
  2333.     /*
  2334.      * Now allocate and load the strings
  2335.      */
  2336.     vim_free(confirm_msg);
  2337.     confirm_msg = alloc(len);
  2338.     if (confirm_msg == NULL)
  2339.     return NULL;
  2340.     *confirm_msg = NUL;
  2341.     hotk = alloc(lenhotkey);
  2342.     if (hotk == NULL)
  2343.     return NULL;
  2344.  
  2345.     *confirm_msg = '\n';
  2346.     STRCPY(confirm_msg + 1, message);
  2347.  
  2348.     p = confirm_msg + 1 + STRLEN(message);
  2349.     q = hotk;
  2350.     r = buttons;
  2351.     *q = (char_u)TO_LOWER(*r);    /* define lowercase hotkey */
  2352.  
  2353.     *p++ = '\n';
  2354.  
  2355.     while (*r)
  2356.     {
  2357.     if (*r == DLG_BUTTON_SEP)
  2358.     {
  2359.         *p++ = ',';
  2360.         *p++ = ' ';        /* '\n' -> ', ' */
  2361.         *(++q) = (char_u)TO_LOWER(*(r + 1)); /* next hotkey */
  2362.         if (dfltbutton)
  2363.         --dfltbutton;
  2364.     }
  2365.     else if (*r == DLG_HOTKEY_CHAR)
  2366.     {
  2367.         r++;
  2368.         if (*r == DLG_HOTKEY_CHAR)        /* '&&a' -> '&a' */
  2369.         *p++ = *r;
  2370.         else
  2371.         {
  2372.         /* '&a' -> '[a]' */
  2373.         *p++ = (dfltbutton == 1) ? '[' : '(';
  2374.         *p++ = *r;
  2375.         *p++ = (dfltbutton == 1) ? ']' : ')';
  2376.         *q = (char_u)TO_LOWER(*r);    /* define lowercase hotkey */
  2377.         }
  2378.     }
  2379.     else
  2380.     {
  2381.         *p++ = *r;        /* everything else copy literally */
  2382.     }
  2383.     r++;
  2384.     }
  2385.     *p++ = ':';
  2386.     *p++ = ' ';
  2387.     *p = NUL;
  2388.     *(++q) = NUL;
  2389.  
  2390.     display_confirm_msg();
  2391.     return hotk;
  2392. }
  2393.  
  2394. /*
  2395.  * Display the ":confirm" message.  Also called when screen resized.
  2396.  */
  2397.     void
  2398. display_confirm_msg()
  2399. {
  2400.     /* avoid that 'q' at the more prompt truncates the message here */
  2401.     ++msg_noquit_more;
  2402.     if (confirm_msg != NULL)
  2403.     msg_puts_attr(confirm_msg, hl_attr(HLF_M));
  2404.     --msg_noquit_more;
  2405. }
  2406.  
  2407. #endif /* FEAT_CON_DIALOG */
  2408.  
  2409. #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
  2410.  
  2411.     int
  2412. vim_dialog_yesno(type, title, message, dflt)
  2413.     int        type;
  2414.     char_u    *title;
  2415.     char_u    *message;
  2416.     int        dflt;
  2417. {
  2418.     if (do_dialog(type,
  2419.         title == NULL ? (char_u *)_("Question") : title,
  2420.         message,
  2421.         (char_u *)_("&Yes\n&No"), dflt, NULL) == 1)
  2422.     return VIM_YES;
  2423.     return VIM_NO;
  2424. }
  2425.  
  2426.     int
  2427. vim_dialog_yesnocancel(type, title, message, dflt)
  2428.     int        type;
  2429.     char_u    *title;
  2430.     char_u    *message;
  2431.     int        dflt;
  2432. {
  2433.     switch (do_dialog(type,
  2434.         title == NULL ? (char_u *)_("Question") : title,
  2435.         message,
  2436.         (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL))
  2437.     {
  2438.     case 1: return VIM_YES;
  2439.     case 2: return VIM_NO;
  2440.     }
  2441.     return VIM_CANCEL;
  2442. }
  2443.  
  2444.     int
  2445. vim_dialog_yesnoallcancel(type, title, message, dflt)
  2446.     int        type;
  2447.     char_u    *title;
  2448.     char_u    *message;
  2449.     int        dflt;
  2450. {
  2451.     switch (do_dialog(type,
  2452.         title == NULL ? (char_u *)"Question" : title,
  2453.         message,
  2454.         (char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
  2455.                                   dflt, NULL))
  2456.     {
  2457.     case 1: return VIM_YES;
  2458.     case 2: return VIM_NO;
  2459.     case 3: return VIM_ALL;
  2460.     case 4: return VIM_DISCARDALL;
  2461.     }
  2462.     return VIM_CANCEL;
  2463. }
  2464.  
  2465. #endif /* FEAT_GUI_DIALOG || FEAT_CON_DIALOG */
  2466.  
  2467. #if defined(FEAT_BROWSE) || defined(PROTO)
  2468. /*
  2469.  * Generic browse function.  Calls gui_mch_browse() when possible.
  2470.  * Later this may pop-up a non-GUI file selector (external command?).
  2471.  */
  2472.     char_u *
  2473. do_browse(saving, title, dflt, ext, initdir, filter, buf)
  2474.     int        saving;        /* write action */
  2475.     char_u    *title;        /* title for the window */
  2476.     char_u    *dflt;        /* default file name */
  2477.     char_u    *ext;        /* extension added */
  2478.     char_u    *initdir;    /* initial directory, NULL for current dir */
  2479.     char_u    *filter;    /* file name filter */
  2480.     buf_T    *buf;        /* buffer to read/write for */
  2481. {
  2482.     char_u        *fname;
  2483.     static char_u    *last_dir = NULL;    /* last used directory */
  2484.     char_u        *tofree = NULL;
  2485.  
  2486.  
  2487.     /* Must turn off browse straight away, or :so autocommands will get the
  2488.      * flag too!  */
  2489.     cmdmod.browse = FALSE;
  2490.  
  2491.     if (title == NULL)
  2492.     {
  2493.     if (saving)
  2494.         title = (char_u *)_("Save File dialog");
  2495.     else
  2496.         title = (char_u *)_("Open File dialog");
  2497.     }
  2498.  
  2499.     /* When no directory specified, use default dir, buffer dir, last dir
  2500.      * or current dir */
  2501.     if (initdir == NULL || *initdir == NUL)
  2502.     {
  2503.     /* When 'browsedir' is a directory, use it */
  2504.     if (mch_isdir(p_bsdir))
  2505.         initdir = p_bsdir;
  2506.     /* When saving or 'browsedir' is "buffer", use buffer fname */
  2507.     else if ((saving || *p_bsdir == 'b')
  2508.         && buf != NULL && buf->b_ffname != NULL)
  2509.     {
  2510.         dflt = gettail(curbuf->b_ffname);
  2511.         tofree = vim_strsave(curbuf->b_ffname);
  2512.         if (tofree != NULL)
  2513.         {
  2514.         initdir = tofree;
  2515.         *gettail(initdir) = NUL;
  2516.         }
  2517.     }
  2518.     /* When 'browsedir' is "last", use dir from last browse */
  2519.     else if (*p_bsdir == 'l')
  2520.         initdir = last_dir;
  2521.     /* When 'browsedir is "current", use current directory.  This is the
  2522.      * default already, leave initdir empty. */
  2523.     }
  2524.  
  2525. # ifdef FEAT_GUI
  2526.     if (gui.in_use)        /* when this changes, also adjust f_has()! */
  2527.     {
  2528.     if (filter == NULL
  2529. #  ifdef FEAT_EVAL
  2530.         && (filter = get_var_value((char_u *)"b:browsefilter")) == NULL
  2531.         && (filter = get_var_value((char_u *)"g:browsefilter")) == NULL
  2532. #  endif
  2533.     )
  2534.         filter = BROWSE_FILTER_DEFAULT;
  2535.     fname = gui_mch_browse(saving, title, dflt, ext, initdir, filter);
  2536.  
  2537.     /* We hang around in the dialog for a while, the user might do some
  2538.      * things to our files.  The Win32 dialog allows deleting or renaming
  2539.      * a file, check timestamps. */
  2540.     need_check_timestamps = TRUE;
  2541.     did_check_timestamps = FALSE;
  2542.     }
  2543.     else
  2544. # endif
  2545.     {
  2546.     /* TODO: non-GUI file selector here */
  2547.     EMSG(_("E338: Sorry, no file browser in console mode"));
  2548.     fname = NULL;
  2549.     }
  2550.  
  2551.     /* keep the directory for next time */
  2552.     if (fname != NULL)
  2553.     {
  2554.     vim_free(last_dir);
  2555.     last_dir = vim_strsave(fname);
  2556.     if (last_dir != NULL)
  2557.     {
  2558.         *gettail(last_dir) = NUL;
  2559.         if (*last_dir == NUL)
  2560.         {
  2561.         /* filename only returned, must be in current dir*/
  2562.         vim_free(last_dir);
  2563.         last_dir = alloc(MAXPATHL);
  2564.         if (last_dir != NULL)
  2565.             mch_dirname(last_dir, MAXPATHL);
  2566.         }
  2567.     }
  2568.     }
  2569.  
  2570.     vim_free(tofree);
  2571.  
  2572.     return fname;
  2573. }
  2574. #endif
  2575.